package com.ruoyi.game.core;

import com.ruoyi.game.core.card.BasePoker;
import com.ruoyi.game.core.card.BasePokerLogic;
import com.ruoyi.game.core.card.CardTypeChecker;
import com.ruoyi.game.core.status.LiangZhuInfo;
import com.ruoyi.game.websocket.handler.GameWebSocketHandler;
import com.ruoyi.game.websocket.session.SessionInfo;
import lombok.*;
import com.ruoyi.game.constant.GameErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.WebSocketSession;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.ruoyi.game.core.card.BasePoker.toCardString;
import com.ruoyi.game.websocket.message.packet.*;

/**
 * 一局座位
 * - 手牌、当局积分
 * - 庄/闲/队伍信息
 * - 本局倍数、底牌等
 */
@Slf4j
@Data
@RequiredArgsConstructor
public class GameSetPos {
    private long playerId;
    private int seatIndex;
    private List<Integer> handCards = new ArrayList<>();            // 手牌
    private LiangZhuInfo liangZhuInfo = null;                       // 已经亮主信息
    private List<Integer> lastPlayed = new ArrayList<>();
    private int score = 0;                                  // 本局最终得分
    private final GameWebSocketHandler socketHandler;

    private transient GameSetCore gameSet;

    public GameSetPos(long playerId, int seatIndex, GameSetCore gameSet) {
        this.playerId = playerId;
        this.seatIndex = seatIndex;
        this.gameSet = gameSet;
        this.socketHandler = gameSet.getSocketHandler();
    }

    private final CardTypeChecker cardTypeChecker = new CardTypeChecker();

    public boolean doOpType(PKOpType opType, List<Integer> cards, GameSetCore gameSetCore, boolean isAuto) {
        log.info("[SetPos] 玩家 {} {} 执行操作 opType={}",
                playerId, isAuto ? "【托管】" : "", opType);

        if (cards != null) {
            if (!cardTypeChecker.check(this, opType, cards, gameSetCore)) {
                log.warn("[SetPos] 操作校验失败：opType={}, cards={}", opType, toCardString(cards));
                return false;
            }
        }
        else {
            if (opType != PKOpType.DA_DU)
                return false;
        }

        // ✅ 执行原有操作逻辑
        return doOpType(opType, cards, gameSetCore);
    }

    public List<Integer> tryAutoCards(PKOpType opType, GameSetCore gameSetCore) {
        return switch (opType) {
            case OUT_CARD, FOLLOW -> GameSetRobotPos.aiChoosePlayCard(this, gameSetCore.getCurrentRound());
            case KOU_DI -> GameSetRobotPos.aiChooseKouDiCards(this);
            case HAN_DA -> {
                int c = GameSetRobotPos.aiChooseHanDaCard(this);
                yield c >= 0 ? List.of(c) : Collections.emptyList();
            }
            case DA_DU -> Collections.emptyList();
            case LIANG_ZHU1 -> GameSetRobotPos.aiChooseLiangZhu1(this, this.gameSet);
            case LIANG_ZHU2 -> GameSetRobotPos.aiChooseLiangZhu2(this, this.gameSet);
            case FAN_ZHU   -> GameSetRobotPos.aiChooseLiangZhu2(this, this.gameSet);
            case ZI_BAO    -> GameSetRobotPos.aiChooseZiBao(this, this.gameSet);
            case ZI_FAN    -> GameSetRobotPos.aiChooseZiFan(this, this.gameSet);
            default        -> Collections.emptyList();
        };
    }

    private boolean doOpType(PKOpType opType, List<Integer> cards, GameSetCore gameSetCore) {
        String cardDescriptions = "";
        if (cards != null) {
            // 将 cards 转换为易读的牌面描述
            cardDescriptions = cards.stream()
                    .map(BasePoker::getCardDescription)
                    .collect(Collectors.joining(", "));

            log.info("[SetPos] 玩家 {} 执行操作 opType={}, cards={}", playerId, opType, cardDescriptions);
        }
        else {
            log.info("[SetPos] 玩家 {} 执行操作 opType={}", playerId, opType);
        }

        boolean success = false;

        switch (opType) {
            case OUT_CARD, FOLLOW -> {
                GameRoundCore currentRound = gameSetCore.getCurrentRound();
                if (currentRound == null) {
                    log.warn("[SetPos] 当前回合为空，无法出牌");
                    WebSocketSession session = GameWebSocketHandler.getSessionFromPlayerId(playerId);
                    if (session != null) {
                        socketHandler.sendError(session, GameErrorCode.INVALID_OP, "当前无出牌回合");
                    }
                    return false;
                }

                // ➤ 校验出牌顺序约束
                if (opType == PKOpType.OUT_CARD && !currentRound.getRoundCards().isEmpty()) {
                    log.warn("[SetPos] 玩家 {} 不能首出（已有其他玩家出牌）", playerId);

                    WebSocketSession session = GameWebSocketHandler.getSessionFromPlayerId(playerId);
                    if (session != null) {
                        socketHandler.sendError(session, GameErrorCode.INVALID_OP, "已有玩家出牌，无法首出");
                    }
                    return false;
                }

                if (opType == PKOpType.FOLLOW && currentRound.getRoundCards().isEmpty()) {
                    log.warn("[SetPos] 玩家 {} 不能跟牌（当前无人出牌）", playerId);
                    return false;
                }

                for (Integer card : cards) {
                    handCards.remove(card); // remove(Object) 只会删除第一次出现的
                }

                setLastPlayed(cards);
                log.info("[SetPos] 玩家 {} 成功 {} 出牌：{} 剩余牌：{}", playerId, opType, toCardString(cards), toCardString(handCards));
                success = true;

                // ✅ 标记回合已操作，并记录出牌信息、比较是否最大、更新出牌者 seat
                currentRound.getRoundCards().addAll(cards);
                currentRound.recordPlayerCards(seatIndex, cards);
                if (opType == PKOpType.OUT_CARD && currentRound.getFirstOutCards().isEmpty()) {
                    log.info("[SetPos] 设置首出 {}", toCardString(cards));
                    currentRound.setFirstOutCards(new ArrayList<>(cards));
                    currentRound.setFirstOutSeat(seatIndex);
                }

                // 设置下一个要出牌玩家的出牌起始时间
                Integer nextSeat = currentRound.findNextSeat(seatIndex);
                if (nextSeat != null) {
                    GameRoundPos nextRoundPos = currentRound.getRoundPosMap().get(nextSeat);
                    if (nextRoundPos != null && !nextRoundPos.isOperated()) {
                        nextRoundPos.setOpStartTime(System.currentTimeMillis() / 1000);
                        currentRound.setCurrentTurnSeat(nextSeat);
                        log.info("[SetPos] 设置 seat={} 的出牌计时器", nextSeat);

                        // ✅ 给下一个玩家推送出牌提醒封包
                        WebSocketSession nextSession = GameWebSocketHandler.getSessionFromPlayerId(
                                gameSetCore.getRoom().getSeats().get(nextSeat).getPlayerId()
                        );
                        Integer nextNextSeat = currentRound.findNextSeat(nextSeat);
                        if (nextSession != null) {
                            // 构造所有座位的状态信息
                            List<PlayerStateInfo> seatStates = new ArrayList<>();
                            List<GameRoomPos> seatList = gameSetCore.getRoom().getSeats();
                            for (int i = 0; i < seatList.size(); i++) {
                                GameRoomPos roomPos = seatList.get(i);
                                PlayerStateInfo info = new PlayerStateInfo();
                                info.setSeatIndex(i);

                                info.setOnline(GameWebSocketHandler.isPlayerOnlineInRoom(roomPos.getPlayerId(), getGameSet().getRoom().getRoomId()) || roomPos.isRobot());
                                info.setRobot(roomPos.isRobot());
                                info.setReady(roomPos.isReady());
                                info.setPlayerName(roomPos.getName());
                                seatStates.add(info);
                            }

                            socketHandler.broadcastPacketToRoom(
                                    gameSetCore.getRoom().getRoomId(),
                                    WsPackets.nextPlayerOp(nextSeat, nextNextSeat, seatStates)
                            );
                            log.info("[SetPos] 推送下一家出牌提醒 seat={}", nextSeat);
                        }
                        else {
                            log.warn("[SetPos] 未找到玩家 {} 的 WebSocketSession[可能为机器人]，无法推送出牌提醒", nextSeat);
                        }
                    }
                }
            }

            case KOU_DI -> {
                if (!handCards.containsAll(cards)) {
                    log.warn("[SetPos] 扣底失败，手牌中缺失：{}", cards);
                    WebSocketSession session = GameWebSocketHandler.getSessionFromPlayerId(playerId);
                    if (session != null) {
                        socketHandler.sendError(session, GameErrorCode.INVALID_OP, "扣底失败，手牌不足");
                    }
                    return false;
                }

                BasePokerLogic.removeExactCards(handCards, cards);
                gameSetCore.setKouPaiList(cards);
                gameSetCore.notifyKouDiResult();

                success = true;
                log.info("[GameSetCore] 玩家 {} 扣底完成，牌型 {}", playerId, toCardString(cards));
            }

            case HAN_DA -> {
                if (cards.isEmpty()) {
                    WebSocketSession session = GameWebSocketHandler.getSessionFromPlayerId(playerId);
                    if (session != null) {
                        socketHandler.sendError(session, GameErrorCode.INVALID_OP, "喊打失败，未选择喊打牌");
                    }
                    return false;
                }
                int card = cards.get(0);
                gameSetCore.setHanDaCard(card);
                this.gameSet.getCurrentRound().setCurrentTurnSeat(seatIndex);
                log.info("[###########SetPos###########] 喊打成功：{}，更新队伍", toCardString(card));

                // 通知喊打结果
                gameSetCore.notifyHandaResult();
                gameSetCore.notifyScoreMultiplier();
                success = true;
            }

            case DA_DU -> {
                gameSetCore.setOneVsFour(true);
                gameSetCore.updateTeamToOneVsFour();
                gameSetCore.setState(SetState.PLAYING_STATE);  // 进入打牌阶段
                this.gameSet.getCurrentRound().setCurrentTurnSeat(seatIndex);
                log.info("[###########SetPos###########] 玩家 {} 执行打独（1打4）", seatIndex);

                // 通知喊打结果
                gameSetCore.notifyHandaResult();
                gameSetCore.notifyScoreMultiplier();
                success = true;
            }

            case LIANG_ZHU1, LIANG_ZHU2, FAN_ZHU, ZI_FAN, ZI_BAO -> {
                if (cards.isEmpty()) {
                    WebSocketSession session = GameWebSocketHandler.getSessionFromPlayerId(playerId);
                    if (session != null) {
                        socketHandler.sendError(session, GameErrorCode.INVALID_OP, "亮主失败，未选择主牌");
                    }
                    return false;
                }

                gameSetCore.callZhu(cards, opType, seatIndex);
                gameSetCore.notifyScoreMultiplier();

                log.info("[SetPos] 玩家 {} 执行亮主相关操作：{}，cards={}", seatIndex, opType, cardDescriptions);
                success = true;
            }

            default -> {
                log.warn("[SetPos] 暂不支持的操作类型：{}", opType);
            }
        }

        log.info("[SetPos] 操作完成：opType={}，success={}", opType, success);
        return success;
    }

    public GameSetCore getGameSet() {
        return this.gameSet;
    }
}
